#pragma once

#include "CompleteQuery.h"
#include "AST.h"
#include "Calls.h"
#include "DesignEntityTable.h"
#include "Follows.h"
#include "Modifies.h"
#include "Parent.h"
#include "ProcTable.h"
#include "Uses.h"
#include "VarTable.h"
#include "CustomException.h"

#include <vector>

/* ------------------------------------------------------------------------------------------
* A singleton class that takes in a Query and returns the results (not implemented yet).
*	
* The Query type is automatically checked by dynamic binding and will be called by its
* respective overloaded function.
*
* The Query object is created by the Query preprocessor using the QueryCreator class.
* 
* Example:Evaluating a query
*
* QueryEvaluator *queryEvaluator = QueryEvaluator::getQueryEvaluator();
* Query *query =  QueryCreator::getQueryCreator()->createQuery(xxx,xxx,xxx);
* Results result = queryEvaluator->evaluateQuery(query);
*
* End Example
* ------------------------------------------------------------------------------------------- */

class QueryEvaluator {
private:
	AST ast; /**< program's AST */
	DesignEntityTable *deTable; /**< Design entity table */
	Follows follows; /**< Follows table */
	Modifies modifies; /**< Modifies table */
	Parent parent; /**< Parent table */
	Uses uses; /**< Uses table */
	VarTable varTable; /**< Variable  table */
	map<string, vector<int>> mapper; /**< Internal declared variable map to list of results */
	bool isAffected;
	vector<pair<int,int>> patternholder;

	vector<int> combineQueries(vector<pair<int,int>> &table1, vector<pair<int,int>> &table2, int join1, int join2);
	vector<int> combineQueriesIdentical(vector<pair<int,int>> &table1, vector<pair<int,int>> &table2, int join1, int join2);

	/**
	 * Evaluates a given such that query
	 * @param query a such that query
	 * @return a vector of integer pair directly from the relationship tables
	 */
	vector<pair<int, int>> evaluateSuchThat(Query *query);

	/**
	 * Evaluates a given pattern query
	 * @param query a pattern query
	 * @return boolean whether the pattern is satisfiable or not, map will be updated internally
	 */
	bool evaluatePattern(Query *query);

	/**
	 * Compute an intersection between 2 vectors
	 * @param vect1 a vector of int
	 * @param vect2 a vector of int
	 * @return a vector of integer that is the intersection of the 2 given vectors.
	 */
	vector<int> intersect(vector<int> vect1, vector<int> vect2);

	/**
	 * Get an initial result list from a DE table
	 * @param vt a variable type to get the result from
	 * @return a vector of integer containing all the values from DE
	 */
	vector<int> getInitialResultList(VAR_TYPE vt);

	/**
	 * Updates the variables mapper
	 * @param param_id an ID to decide which pair is taken
	 * @param param_type the variable type to be updated
	 * @param param_name the parameter name to be updated
	 * @param res a result vector from such that queries
	 * @return a boolean indicating whether a result is true or false
	 */
	bool updateMap(VAR_TYPE param1_type, string param1_name, VAR_TYPE param2_type, string param2_name,vector<pair<int,int>>& res);

public:
	/** Constructor
	 * Creates a QueryEvaluator
	 * @param ast AST
	 * @param deTable A design entity table
	 * @param follows Follows table
	 * @param modifies Modifies table
	 * @param parent Parent table
	 * @param uses Uses table
	 * @param varTable Variable table
	 */
	QueryEvaluator(AST& ast, DesignEntityTable* deTable, Follows& follows, Modifies& modifies, Parent& parent, Uses& uses, VarTable& varTable);

	/**
	 * Evaluates a given complete query
	 * @param completeQuery a complete query
	 * @return a list of string to answer the complete query
	 */
	list<string> evaluateCompleteQuery(CompleteQuery *completeQuery);

	
	//Destructor
	~QueryEvaluator();
};